package com.design.framework.utils;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.persistence.Id;
import javax.persistence.Table;
import org.apache.commons.collections4.MapUtils;
import org.springframework.format.annotation.DateTimeFormat;

/**
 * 反射设置值工具类
 *
 * @author JohnDeng
 * @dateTime 2018年5月2日下午5:21:43
 */
public class MyBeanUtils {

  /**
   * 获取set方法
   *
   * @param object   对象
   * @param property 属性名
   * @param value    属性值
   * @return
   * @author JohnDeng 2017年11月9日下午3:05:12
   */
  public static String setMethodName(Object object, String property, Object value) {
    String methodName = "set" + property.substring(0, 1).toUpperCase();
    if (property.length() > 1) {
      methodName += property.substring(1);
    }
    return methodName;
  }

  /**
   * 获取get方法
   *
   * @param property 对象
   * @return
   * @author JohnDeng 2017年11月9日下午3:04:55
   */
  public static String getMethodName(String property) {
    String methodName = "get" + property.substring(0, 1).toUpperCase();
    if (property.length() > 1) {
      methodName += property.substring(1);
    }
    return methodName;
  }

  /**
   * 获取@Id的值
   *
   * @param object 对象
   * @return
   * @author JohnDeng 2017年11月9日下午3:21:46
   */
  public static Object getIdValue(Object object) {
    Class<?> clazz = object.getClass();
    List<Field> fields = ReflectUtils.getFields(clazz);
    for (Field field : fields) {
      Id id = field.getAnnotation(Id.class);
      if (id != null) {
        try {
          String methodName = MyBeanUtils.getMethodName(field.getName());
          Method method = clazz.getMethod(methodName);
          method.setAccessible(true);
          return method.invoke(object);
        } catch (Exception e) {
          e.printStackTrace();
        }

      }
    }
    return null;
  }

  /**
   * 设置实体创建时间
   *
   * @param object
   * @author JohnDeng 2017年11月9日下午4:24:04
   */
  public static void setCreateTimeValue(Object object) {
    Class<?> clazz = object.getClass();
    List<Field> fields = ReflectUtils.getFields(clazz);
    for (Field field : fields) {
      DateTimeFormat dateTimeFormat = field.getAnnotation(DateTimeFormat.class);
      if (dateTimeFormat != null) {
        if ("createTime".equals(field.getName())) {
          setProperty(object, field.getName(), new Date());
        }
      }
    }
  }

  /**
   * 设置id值为UUID
   *
   * @param object
   * @author JohnDeng 2017年11月9日下午4:26:44
   */
  public static String setIdValue(Object object) {
    String uuid = UUID.randomUUID().toString();
    Class<?> clazz = object.getClass();
    List<Field> fields = ReflectUtils.getFields(clazz);
    for (Field field : fields) {
      Id id = field.getAnnotation(Id.class);
      if (id != null) {
        if ("id".equals(field.getName())) {
          setProperty(object, field.getName(), uuid);
        }
      }
    }
    return uuid;
  }

  /**
   * 设置属性值
   *
   * @param object   对象
   * @param property 属性名
   * @param value    属性值
   * @author JohnDeng 2017年11月9日下午4:21:34
   */
  public static void setProperty(Object object, String property, Object value) {
    String methodName = "set" + property.substring(0, 1).toUpperCase();
    if (property.length() > 1) {
      methodName += property.substring(1);
    }
    String[] methodNames = new String[1];
    methodNames[0] = methodName;
    setMethodInvoke(object, methodNames, value);
  }

  public static void setMethodInvoke(Object object, String[] methodNames, Object value) {
    Method[] methods = object.getClass().getMethods();
    for (String methodName : methodNames) {
      for (Method method : methods) {
        if (method.getName().equals(methodName)) {
          try {
            method.invoke(object, new Object[]{value});
          } catch (Exception e) {
            e.printStackTrace();
          }
        }
      }
    }
  }

  public static Object getProperty(Object object, String property) {
    String methodName = "get" + property.substring(0, 1).toUpperCase();
    if (property.length() > 1) {
      methodName += property.substring(1);
    }
    String[] methodNames = new String[2];
    methodNames[0] = methodName;
    return getMethodInvoke(object, methodNames);
  }

  public static Object getMethodInvoke(Object object, String[] methodNames) {
    Method[] methods = object.getClass().getMethods();
    for (String methodName : methodNames) {
      for (Method method : methods) {
        if (method.getName().equals(methodName)) {
          try {
            return method.invoke(object, new Object[]{});
          } catch (Exception e) {
            e.printStackTrace();
          }
        }
      }
    }
    return null;
  }

  public static <T> T newTclass(Class<T> clazz) throws Exception {
    return clazz.newInstance();
  }

  /**
   * 获取实体注解的tableName
   *
   * @param object
   * @return
   * @author John
   * @dateTime 2017年11月30日上午11:44:10
   */
  public static String getTableName(Object object) {
    Class<?> clazz = object.getClass();
    Table table = clazz.getAnnotation(Table.class);
    if (table != null) {
      Method[] met = table.annotationType().getDeclaredMethods();
      for (Method me : met) {
        if (!me.isAccessible()) {
          me.setAccessible(true);
        }
        try {
          if ("name".equals(me.getName())) {
            return (String) me.invoke(table);
          }
        } catch (IllegalAccessException e) {
          e.printStackTrace();
        } catch (IllegalArgumentException e) {
          e.printStackTrace();
        } catch (InvocationTargetException e) {
          e.printStackTrace();
        }
      }
    }
    return null;
  }

  /**
   * 实体转MAP
   *
   * @return
   * @throws IntrospectionException
   * @throws InvocationTargetException
   * @throws IllegalAccessException
   * @author JohnDeng
   * @dateTime 2019年5月28日上午9:57:52
   */
  public static Map<String, String> beanToMap(Object bean) throws Exception {
    // 获取对象字节码信息,不要Object的属性
    BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass(), Object.class);
    // 获取bean对象中的所有属性
    PropertyDescriptor[] list = beanInfo.getPropertyDescriptors();
    Map<String, String> map = new HashMap<String, String>(list.length);
    for (PropertyDescriptor pd : list) {
      // 获取属性名
      String key = pd.getName();
      // 调用getter()方法,获取内容
      String value = String.valueOf(pd.getReadMethod().invoke(bean));
      // 增加到map集合当中
      map.put(key, value);
    }
    return map;
  }


  /**
   * map 转map
   *
   * @param mapObject
   * @return
   * @throws Exception
   * @author JohnDeng
   * @dateTime 2019年5月28日上午10:42:08
   */
  public static Map<String, String> mapObjectToMapString(Map<String, Object> mapObject) throws Exception {
    Map<String, String> map = null;
    if (MapUtils.isNotEmpty(mapObject)) {
      map = new HashMap<>(mapObject.size());
      for (Map.Entry<String, Object> entry : mapObject.entrySet()) {
        map.put(entry.getKey(), String.valueOf(entry.getValue()));
      }
    }
    return map;
  }

}
